package com.dlc.shop.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.poi.excel.ExcelUtil;
import cn.hutool.poi.excel.ExcelWriter;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.huifu.bspay.sdk.opps.core.request.V2UserBusiOpenRequest;
import com.dlc.shop.allinpay.service.AllinpayCompanyService;
import com.dlc.shop.bean.app.dto.ShopHeadInfoDto;
import com.dlc.shop.bean.app.param.ShopAuditingParam;
import com.dlc.shop.bean.dto.ShopCreateInfoDTO;
import com.dlc.shop.bean.dto.ShopSigningInfoDTO;
import com.dlc.shop.bean.dto.ShopUserRegisterDto;
import com.dlc.shop.bean.dto.allinpay.AllinpayShopBankCardDTO;
import com.dlc.shop.bean.enums.AuditStatus;
import com.dlc.shop.bean.enums.*;
import com.dlc.shop.bean.event.*;
import com.dlc.shop.bean.model.*;
import com.dlc.shop.bean.param.*;
import com.dlc.shop.bean.vo.ShopCompanyVO;
import com.dlc.shop.bean.vo.ShopDetailVO;
import com.dlc.shop.common.allinpay.constant.*;
import com.dlc.shop.common.config.Constant;
import com.dlc.shop.common.constants.CacheNames;
import com.dlc.shop.common.enums.SysTypeEnum;
import com.dlc.shop.common.exception.YamiShopBindException;
import com.dlc.shop.common.i18n.I18nMessage;
import com.dlc.shop.common.util.*;
import com.dlc.shop.dao.ProductMapper;
import com.dlc.shop.dao.ShopDetailMapper;
import com.dlc.shop.dao.ShopWalletMapper;
import com.dlc.shop.service.*;
import com.dlc.shop.wukongim.service.WuKongImService;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.poi.ss.usermodel.Sheet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.aop.framework.AopContext;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author lgh on 2018/08/29.
 */
@Service
public class ShopDetailServiceImpl extends ServiceImpl<ShopDetailMapper, ShopDetail> implements ShopDetailService {
    private static final Logger log = LoggerFactory.getLogger(ShopDetailServiceImpl.class);

    @Autowired
    private ShopDetailMapper shopDetailMapper;
    @Autowired
    private ShopAuditingService shopAuditingService;
    @Autowired
    private ShopWalletMapper shopWalletMapper;
    @Autowired
    private OfflineHandleEventService offlineHandleEventService;
    @Autowired
    private ProductMapper productMapper;
    @Autowired
    private ApplicationContext applicationContext;
    @Autowired
    private ApplicationEventPublisher eventPublisher;
    @Autowired
    @Lazy
    private ShopCompanyService shopCompanyService;
    @Autowired
    @Lazy
    private ShopBankCardService shopBankCardService;
    @Autowired
    private CategoryShopService categoryShopService;
    @Autowired
    private BrandShopService brandShopService;
    @Autowired
    private SupplierService supplierService;
    @Autowired
    private ProdCommService prodCommService;
    @Autowired
    private AllinpayCompanyService allinpayCompanyService;
    @Autowired
    private CompanyAuditingService companyAuditingService;
    @Autowired
    @Lazy
    private ImChannelService imChannelService;
    @Autowired
    private WuKongImService wuKongImService;
    @Autowired
    private WarehouseService warehouseService;

    @Lazy
    @Autowired
    private HuifuService huifuService;

    /**
     * 导出excel列（中文）
     */
    private static final String[] EXPORT_COL = {
            I18nMessage.getMessage("yami.shop.detail.excel.header.shopName"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.businessName"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.status"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.phone"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.phone"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.intro"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.applyTime"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.type"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.signStartTime"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.signEndTime"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.scope"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.socialCode"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.companyName"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.domicile"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.legalPerson"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.registerPrice"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.registerTime"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.businessStartTime"),
            I18nMessage.getMessage("yami.shop.detail.excel.header.businessEndTime")
    };

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public void updateShopDetail(ShopDetail shopDetail) {
        // 若经纬度数据变更，需清空同城配送中的位置信息
        ShopDetail detailDb = this.getById(shopDetail.getShopId());
        this.checkShopInfo(shopDetail, false);
        if (!PrincipalUtil.isDbPhone(shopDetail.getTel(), detailDb.getTel(), true)) {
            throw new YamiShopBindException("yami.user.err.phone");
        }
        if (shopDetail.getTel().contains(Constant.ASTERISK)) {
            shopDetail.setTel(detailDb.getTel());
        }
//        boolean checkLocation = detailDb.getShopLng() != null && detailDb.getShopLat() != null;
//        boolean check = checkLocation && (!detailDb.getShopLat().equals(shopDetail.getShopLat()) || !detailDb.getShopLng().equals(shopDetail.getShopLng()));
//        if (check) {
//            applicationContext.publishEvent(new ClearPolygonPathEvent(shopDetail.getShopId()));
//        }
        updateById(shopDetail);
        // 给还没创建通联会员的商家创建
        if (allinpayCompanyService.getIsAllinpay() && Objects.equals(detailDb.getIsCreateMember(), 0)) {
            createAllinpayMemberByShopId(detailDb.getShopId());
        }
        if (!Objects.equals(shopDetail.getShopName(), detailDb.getShopName()) || !Objects.equals(shopDetail.getShopLogo(), detailDb.getShopLogo())) {
            // 修改logo和店铺名称就发送一条更新信息cmd
            imChannelService.updateMember(null, detailDb.getShopId(), null);
        }
    }

    @Override
    public double getDistance(Double lat, Double lng, Long shopId) {
        return shopDetailMapper.getDistance(lat, lng, shopId);
    }

    @Override
    @Cacheable(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public ShopDetail getShopDetailByShopId(Long shopId) {
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        ShopAuditing shopAuditing = shopAuditingService.getOne(new LambdaQueryWrapper<ShopAuditing>().eq(ShopAuditing::getShopId, shopId));
        if (Objects.nonNull(shopAuditing) && Objects.equals(shopAuditing.getStatus(), AuditStatus.SUCCESSAUDIT.value())) {
            shopDetail.setIsPassShop(1);
        } else {
            shopDetail.setIsPassShop(0);
        }
        boolean shopTypeCheck = Objects.nonNull(shopDetail) && !Objects.equals(shopDetail.getShopId(),Constant.PLATFORM_SHOP_ID);
        if (shopTypeCheck && allinpayCompanyService.getIsAllinpay()) {
            // 通联是上线待审核的话店铺状态也做对应展示
            setAllinpayShopStatus(shopDetail);
        }
        return shopDetail;
    }

    private static void setAllinpayShopStatus(ShopDetail shopDetail) {
        if (Objects.isNull(shopDetail)) {
            return;
        }
        boolean offline = Objects.equals(shopDetail.getAllinpayShopStatus(), AllinpayShopStatus.UN_AVAILABLE.value())
                && (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.APPLYING.value()) && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.OPEN_AWAIT_AUDIT.value()));
        if (Objects.equals(shopDetail.getAllinpayShopStatus(), AllinpayShopStatus.WAIT_AUDIT.value())) {
            shopDetail.setShopStatus(ShopStatus.OFFLINE_AUDIT.value());
        }
        if (Objects.equals(shopDetail.getAllinpayShopStatus(), AllinpayShopStatus.OPEN_WAIT_AUDIT.value())) {
            shopDetail.setShopStatus(ShopStatus.OPEN_AWAIT_AUDIT.value());
        }
        if (Objects.equals(shopDetail.getAllinpayShopStatus(), AllinpayShopStatus.OFFLINE.value()) || offline) {
            shopDetail.setShopStatus(ShopStatus.OFFLINE.value());
        }
        if (Objects.equals(shopDetail.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.FAIL.value())
                && Objects.equals(shopDetail.getAllinpayShopStatus(), AllinpayShopStatus.OFFLINE.value())) {
            shopDetail.setShopStatus(ShopStatus.AUDIT_FAIL.value());
        }
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void removeShopDetailCacheByShopId(Long shopId) {
    }



    @Override
    public ShopDetail getShopByMobile(String mobile) {
        return shopDetailMapper.getShopByMobile(mobile);
    }

    @Override
    public void updatePasswordByUserName(String username, String newPassword) {
        shopDetailMapper.updatePasswordByUserName(username, newPassword);
    }

    @Override
    public ShopDetail getShopDetailByUserId(String userId) {
        ShopDetail shopDetail = shopDetailMapper.getShopDetailByUserId(userId);
        boolean shopTypeCheck = Objects.nonNull(shopDetail) && !Objects.equals(shopDetail.getShopId(),Constant.PLATFORM_SHOP_ID);
        if (shopTypeCheck && allinpayCompanyService.getIsAllinpay()) {
            // 通联是上线待审核的话店铺状态也做对应展示
            setAllinpayShopStatus(shopDetail);
        }
        return shopDetail;
    }

    /**
     * 申请开店
     *
     * @param userId
     * @param shopDetailParam
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void applyShop(String userId, ShopDetailParam shopDetailParam) {
        ShopDetail shopDetail = getShopDetailByUserId(userId);
        if (shopDetail != null && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.NOTOPEN.value())) {
            // 您已经申请开启店铺,不能重新申请
            throw new YamiShopBindException("yami.cannot.reapply");
        }
        ShopDetail dbShopnameShop = shopDetailMapper.selectOne(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopName, shopDetailParam.getShopName()).ne(ShopDetail::getUserId, userId));
        if (dbShopnameShop != null) {
            // 店铺名称已存在
            throw new YamiShopBindException("yami.store.name.exist");
        }
        ShopDetail newShopDetail = BeanUtil.map(shopDetailParam, ShopDetail.class);

        Date now = new Date();
        // 如果是第一次申请开店
        if (shopDetail == null) {
            newShopDetail.setUserId(userId);
            newShopDetail.setCreateTime(now);
            newShopDetail.setShopOwner(userId);
            newShopDetail.setShopStatus(ShopStatus.NOTOPEN.value());
            newShopDetail.setIsDistribution(1);
        } else {
            newShopDetail.setShopId(shopDetail.getShopId());
            newShopDetail.setCreateTime(now);
        }


        newShopDetail.setUpdateTime(now);
        // 保存或更新
        saveOrUpdate(newShopDetail);
        //清除缓存
        removeShopDetailCacheByShopId(newShopDetail.getShopId());

        // 插入一条审核记录
        ShopAuditing auditing = shopAuditingService.getShopAuditingByUserId(userId);
        if (auditing == null) {
            auditing = new ShopAuditing();
            auditing.setShopId(newShopDetail.getShopId());
            auditing.setUserId(userId);
            auditing.setCreateTime(new Date());
        }
        auditing.setStatus(AuditStatus.WAITAUDIT.value());
        auditing.setUpdateTime(new Date());
        shopAuditingService.saveOrUpdate(auditing);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean audit(ShopAuditingParam shopAuditingParam) {
        ShopAuditing dbShopAuditing = shopAuditingService.getOne(Wrappers.lambdaQuery(ShopAuditing.class).eq(ShopAuditing::getShopId, shopAuditingParam.getShopId()));
        if (Objects.isNull(dbShopAuditing)) {
            throw new YamiShopBindException("该店铺没有提交审核");
        }
        if (!Objects.equals(dbShopAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
            log.error("店铺{}开店状态为:{}", dbShopAuditing.getShopId(), dbShopAuditing.getStatus());
            throw new YamiShopBindException("店铺不处于待审核状态");
        }
        Date now = new Date();
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopAuditingId(dbShopAuditing.getShopAuditingId());
        shopAuditing.setShopId(shopAuditingParam.getShopId());
        shopAuditing.setAuditorId(shopAuditingParam.getAuditorId());
        shopAuditing.setUpdateTime(now);
        shopAuditing.setStatus(shopAuditingParam.getStatus());
        shopAuditing.setRemarks(shopAuditingParam.getRemarks());
        shopAuditingService.updateById(shopAuditing);
        // 获取店铺信息
        ShopDetail shopDetail = getById(shopAuditingParam.getShopId());

        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        // 审核不通过
        if (Objects.equals(shopAuditingParam.getStatus(), AuditStatus.FAILAUDIT.value())) {
            shopDetail.setShopStatus(ShopStatus.APPLYING.value());
        }
        // 审核通过
        else {
            shopDetail.setIsSupplier(shopAuditingParam.getIsSupplier());
            shopDetail.setType(shopAuditingParam.getShopType());
            if (allinpayCompanyService.getIsAllinpay()) {
                shopDetail.setShopStatus(ShopStatus.OPEN.value());
            } else {
                auditSuccess(shopDetail, shopAuditingParam.getContractStartTime(), shopAuditingParam.getContractEndTime(), now);
            }
            boolean notExist = shopWalletMapper.selectCount(new LambdaQueryWrapper<ShopWallet>().eq(ShopWallet::getShopId, shopDetail.getShopId()).eq(ShopWallet::getPaySysType, paySysType)) < 1;
            if (notExist) {
                saveShopWallet(shopDetail.getShopId(), allinpayCompanyService.getIsAllinpay());
            }
            updateShopCompanyStatus(shopDetail.getShopId(), AuditStatus.SUCCESSAUDIT.value());
            // 新店初始化事件
            applicationContext.publishEvent(new OpenShopInitEvent(shopDetail));
            // 添加默认供应商
            saveSupplier(shopDetail);
            // 把商家自定义品牌添加为平台品牌
            brandShopService.updateCustomBrandToPlatformBrandByShopId(shopAuditingParam.getShopId());
            // 更新签约分类与品牌的状态
            categoryShopService.changeStatusByShopIdAndStatus(shopAuditingParam.getShopId(), SigningStatus.PENDING_REVIEW.value(), SigningStatus.SUCCESS.value());
            brandShopService.changeStatusByShopIdAndStatus(shopAuditingParam.getShopId(), SigningStatus.PENDING_REVIEW.value(), SigningStatus.SUCCESS.value());
            // 添加默认仓库
            warehouseService.createWarehouseByShopId(shopAuditingParam.getShopId(), SysTypeEnum.MULTISHOP.value(), shopDetail.getTel(), shopDetail.getUserName());
//            try {
//                if(shopDetail.getHuifuId() == null || shopDetail.getHuifuId().equals("")) {
//                    Map<String, Object> huifuRes = huifuService.huifuOpen(shopDetail);
//                    if(huifuRes.get("resp_code").equals("00000000")) {
//                        shopDetail.setHuifuId(huifuRes.get("huifu_id").toString());
//                        shopDetail.setLoginName(huifuRes.get("login_name").toString());
//                        shopDetail.setLoginPassword(huifuRes.get("login_password").toString());
//                    } else {
//                        throw new RuntimeException(huifuRes.get("resp_desc").toString());
//                    }
//                }
//                Map<String, Object> bindRes = huifuService.huifuBind(shopDetail);
//                if(!bindRes.get("resp_code").equals("00000000")) {
//                    throw new RuntimeException(bindRes.get("resp_desc").toString());
//                }
//            } catch (Exception e) {
//                throw new RuntimeException(e);
//            }
        }
        updateById(shopDetail);
        return true;
    }

    /**
     *  更新店铺工商信息审核状态
     * @param shopId
     * @param status
     */
    private void updateShopCompanyStatus(Long shopId, Integer status) {
        ShopCompanyVO shopCompanyWaitAudit = shopCompanyService.getShopCompanyByShopIdAndStatus(shopId, AuditStatus.WAITAUDIT.value());
        if (Objects.isNull(shopCompanyWaitAudit)) {
            throw new YamiShopBindException("缺少店铺工商资料");
        }
        ShopCompany shopCompany = BeanUtil.map(shopCompanyWaitAudit, ShopCompany.class);
        shopCompany.setStatus(status);
        shopCompanyService.updateByShopId(shopCompany);
    }

    private void auditSuccess(ShopDetail shopDetail, Date startTime, Date endTime, Date now) {
        shopDetail.setContractStartTime(DateUtil.beginOfDay(startTime));
        shopDetail.setContractEndTime(Objects.isNull(endTime) ? endTime : getSaveEndOfDay(endTime));
        if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && (Objects.isNull(shopDetail.getContractEndTime()) || now.compareTo(shopDetail.getContractEndTime()) < 0)) {
            // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
            shopDetail.setShopStatus(ShopStatus.OPEN.value());
        } else {
            // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
            shopDetail.setShopStatus(ShopStatus.STOP.value());
        }
    }

    private void saveSupplier(ShopDetail shopDetail) {
        Supplier supplier = new Supplier();
        supplier.setShopId(shopDetail.getShopId());
        supplier.setStatus(1);
        supplier.setSupplierName("自采供应商");
        supplier.setCreateTime(new Date());
        supplier.setIsDefault(1);
        supplierService.save(supplier);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopDetail.shopId")
    public Long offline(ShopDetail shopDetail, String offlineReason, Long sysUserId) {
        // 添加下线处理记录
        Date now = new Date();
        OfflineHandleEvent offlineHandleEvent = new OfflineHandleEvent();
        offlineHandleEvent.setHandleId(shopDetail.getShopId());
        offlineHandleEvent.setHandleType(OfflineHandleEventType.SHOP.getValue());
        offlineHandleEvent.setCreateTime(now);
        offlineHandleEvent.setOfflineReason(offlineReason);
        offlineHandleEvent.setHandlerId(sysUserId);
        offlineHandleEvent.setShopId(shopDetail.getShopId());
        offlineHandleEvent.setStatus(allinpayCompanyService.getIsAllinpay() ? OfflineHandleEventStatus.APPLY_BY_SHOP.getValue() : OfflineHandleEventStatus.OFFLINE_BY_PLATFORM.getValue());
        offlineHandleEvent.setUpdateTime(now);
        offlineHandleEventService.save(offlineHandleEvent);

        // 更新店铺状态为下线
        shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OFFLINE.value());

        // 将该店铺所有的商品下线状态
        productMapper.offlineProdByShopIds(Collections.singletonList(shopDetail.getShopId()));

        // 发送店铺违规下线事件
        applicationContext.publishEvent(new ShopChangeStatusEvent(shopDetail.getShopId(), ShopStatus.OFFLINE));
//        // 发送批量消息
//        List<String> channelIds = imChannelService.listChannelByShopId(shopDetail.getShopId());
//        if (CollUtil.isNotEmpty(channelIds)) {
//            wuKongImService.messageSendbatch(shopDetail.getShopId() + StrUtil.DASHED + ShopStatus.OFFLINE.value(), channelIds, WuKongConstant.SHOP_STATUS);
//        }
        return offlineHandleEvent.getEventId();
    }


    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventAuditParam.handleId")
    public void auditOfflineShop(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        ShopDetailService shopDetailService = (ShopDetailService) AopContext.currentProxy();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(offlineHandleEventAuditParam.getHandleId());
        if (Objects.isNull(shopDetail)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value())) {
            // 店铺不处于待审核状态
            throw new YamiShopBindException("店铺已经审核，请刷新页面");
        }
        Date now = new Date();
        // 审核通过
        if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.AGREE_BY_PLATFORM.getValue())) {
            auditSuccess(shopDetail, now);
        }
        // 审核不通过
        else if (Objects.equals(offlineHandleEventAuditParam.getStatus(), OfflineHandleEventStatus.DISAGREE_BY_PLATFORM.getValue())) {
            shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OFFLINE.value());
        }
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#offlineHandleEventAuditParam.handleId")
    public void onlineOpenShop(OfflineHandleEventAuditParam offlineHandleEventAuditParam, Long sysUserId) {
        if (!allinpayCompanyService.getIsAllinpay()) {
            throw new YamiShopBindException("开通通联支付后才可以直接上线商家");
        }

        ShopDetailService shopDetailService = (ShopDetailService) AopContext.currentProxy();
        ShopDetail shopDetail = shopDetailService.getShopDetailByShopId(offlineHandleEventAuditParam.getHandleId());
        if (Objects.isNull(shopDetail)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE_AUDIT.value()) && !Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            // 店铺不处于待审核状态
            throw new YamiShopBindException("店铺状态已发生变化，请刷新后重试");
        }
        auditSuccess(shopDetail, new Date());
        offlineHandleEventService.auditOfflineEvent(offlineHandleEventAuditParam, sysUserId);
    }

    private void auditSuccess(ShopDetail shopDetail, Date now) {
        if (allinpayCompanyService.getIsAllinpay()) {
            shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OPEN.value());
            return;
        }
        if (now.compareTo(shopDetail.getContractStartTime()) >= 0 && (Objects.isNull(shopDetail.getContractEndTime()) || now.compareTo(shopDetail.getContractEndTime()) < 0)) {
            // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
            shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.OPEN.value());
        } else {
            // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
            shopDetailMapper.updateStatus(shopDetail.getShopId(), ShopStatus.STOP.value());
        }
    }

    @Override
    public List<ShopHeadInfoDto> listHotShopsHead() {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        return shopDetailMapper.listHotShopsHead(paySysType);
    }

    @Override
    public Page<ShopHeadInfoDto> searchShops(PageParam<ShopHeadInfoDto> page, ShopHeadInfoDto shopHeadInfoDto) {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        return shopDetailMapper.searchShops(page, shopHeadInfoDto, paySysType);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void insertDetail(ShopDetail shopDetail, long count) {
        Date date = new Date();
        shopDetail.setShopStatus(1);
        shopDetail.setIsDistribution(1);
        shopDetail.setCreateTime(date);
        shopDetail.setUpdateTime(date);
        if ((this.checkMobile(shopDetail.getMobile(), null) + count) > 0) {
            // 该账号已存在，请重新输入
            throw new YamiShopBindException("yami.store.account.exist");
        }
        long nameCount = count(new LambdaQueryWrapper<ShopDetail>().eq(ShopDetail::getShopName, shopDetail.getShopName())
                .eq(ShopDetail::getShopStatus, 1).ne(ShopDetail::getShopId, shopDetail.getShopId()));
        if (nameCount > 0) {
            // 已有相同名称
            throw new YamiShopBindException("yami.shop.name.have.already");
        }
        shopDetailMapper.insert(shopDetail);
        //创建店铺钱包
        saveShopWallet(shopDetail.getShopId(), allinpayCompanyService.getIsAllinpay());
        // 通联创建会员
        allinpayCompanyService.createAllinpayCompanyMember(shopDetail.getShopId());
    }

    @Override
    public long checkMobile(String mobile, Long shopId) {
        return count(new LambdaQueryWrapper<ShopDetail>()
                .eq(ShopDetail::getMobile, mobile)
                .ne(Objects.nonNull(shopId), ShopDetail::getShopId, shopId)
        );
    }

    @Override
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void updatePasswordOrMobile(Long shopId, String password, String mobile, Long count) {
        ShopDetail shopDetail = new ShopDetail();
        shopDetail.setShopId(shopId);

        shopDetail.setPassword(password);
        if (Objects.nonNull(mobile)) {
            if ((this.checkMobile(shopDetail.getMobile(), shopId) + count) > 0) {
                // 该账号已存在，请重新输入
                throw new YamiShopBindException("yami.store.account.exist");
            }
            shopDetail.setMobile(mobile);
        }
        shopDetailMapper.updateById(shopDetail);
        // 店铺员工表更新超级管理员账号密码
        applicationContext.publishEvent(new UpdateShopSuperAdminAccountEvent(shopDetail));
    }

    @Override
    public void batchUpdateShopType(ShopTypeParam shopTypeParam) {
        List<Long> shopIds = shopTypeParam.getShopIds();
        Integer type = shopTypeParam.getType();
        // 修改店铺类型
        if (CollUtil.isEmpty(shopIds)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.select.a.shop");
        }
        if (Objects.isNull(type)) {
            // 未找到店铺信息
            throw new YamiShopBindException("yami.select.only.shop.type");
        }
        shopDetailMapper.batchUpdateShopType(shopIds, type);
        this.removeCacheByShopIds(shopIds);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ShopCreateInfoDTO platformCreateShop(ShopCreateInfoDTO shopCreateInfoDTO, Long userId) {
        boolean isAllinpay = allinpayCompanyService.getIsAllinpay();
        ShopUserRegisterDto shopUserRegisterDto = shopCreateInfoDTO.getShopUserRegisterInfo();
        // 保存店铺基本信息
        Date now = new Date();
        ShopDetail shopDetail = shopCreateInfoDTO.getShopDetail();
        this.checkShopInfo(shopDetail, true);
        savePlatformShopDetail(isAllinpay, shopUserRegisterDto, now, shopDetail);
        Long shopId = shopDetail.getShopId();
        // 通联创建企业会员
        allinpayCompanyService.createAllinpayCompanyMember(shopId);
        // 初始化店铺数据
        saveShopWallet(shopId, allinpayCompanyService.getIsAllinpay());
        // 初始化店铺审核信息，平台端创建店铺默认为审核成功
        ShopAuditing shopAuditing = new ShopAuditing();
        shopAuditing.setShopId(shopId);
        shopAuditing.setAuditorId(userId);
        shopAuditing.setCreateTime(now);
        shopAuditing.setUpdateTime(now);
        shopAuditing.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        shopAuditingService.save(shopAuditing);
        // 添加默认供应商
        saveSupplier(shopDetail);
        // 保存店铺工商信息
        ShopCompany shopCompany = shopCreateInfoDTO.getShopCompany();
        shopCompany.setShopId(shopDetail.getShopId());
        shopCompany.setStatus(isAllinpay ? AuditStatus.WAITAUDIT.value() : AuditStatus.SUCCESSAUDIT.value());
        shopCompanyService.saveInfo(shopCompany);
        // 保存分类签约信息
        categoryShopService.insertBatchByShopId(shopCreateInfoDTO.getCategorySigningList(), shopId, SigningStatus.SUCCESS.value());
        // 保存品牌签约信息
        brandShopService.insertBatchByShopId(shopCreateInfoDTO.getBrandSigningList(), shopId, SigningStatus.SUCCESS.value());
        // 店铺员工表插入一个超级管理员
        shopUserRegisterDto.setShopId(shopId);
        applicationContext.publishEvent(new ShopEmployeeSuperAdminEvent(shopUserRegisterDto));
        // 初始化会员权益
        applicationContext.publishEvent(new OpenShopInitEvent(shopDetail));
        // 保存店铺银行卡信息
        saveShopBankCard(shopCreateInfoDTO, shopId, shopCompany);
        // 创建默认仓库
        warehouseService.createWarehouseByShopId(shopId, SysTypeEnum.MULTISHOP.value(), shopDetail.getTel(), shopDetail.getUserName());
    return shopCreateInfoDTO;
    }

    private void saveShopBankCard(ShopCreateInfoDTO shopCreateInfoDTO, Long shopId, ShopCompany shopCompany) {
        if (allinpayCompanyService.getIsAllinpay()) {
            AllinpayShopBankCardDTO allinpayShopBankCardDTO = shopCreateInfoDTO.getAllinpayShopBankCardDTO();
            if (Objects.isNull(allinpayShopBankCardDTO)) {
                // 至少绑定一个对公户账户
                throw new YamiShopBindException("yami.allinpay.bank.not.null");
            }
            shopBankCardService.insertAndSetCompanyInfo(allinpayShopBankCardDTO, shopId, shopCompany);
        } else {
            shopBankCardService.saveBatchByShopId(shopCreateInfoDTO.getShopBankCardList(), shopId);
        }
    }

    private void savePlatformShopDetail(boolean isAllinpay, ShopUserRegisterDto shopUserRegisterDto, Date now, ShopDetail shopDetail) {
        shopDetail.setCreateTime(now);
        shopDetail.setUpdateTime(now);
        shopDetail.setIsPlatform(1);
        if (!isAllinpay) {
            if (Objects.isNull(shopDetail.getContractStartTime())) {
                throw new YamiShopBindException("店铺签约时间不能为空");
            }
            auditSuccess(shopDetail, shopDetail.getContractStartTime(), shopDetail.getContractEndTime(), now);
        } else {
            shopDetail.setShopStatus(ShopStatus.OPEN.value());
            shopDetail.setType(ShopType.PREFERRED_STORES.value());
            shopDetail.setIsSupplier(ShopSupplierModel.THIRD_PARTY_STORES.value());
            shopDetail.setAllinpayShopStatus(AllinpayShopStatus.OPEN_WAIT_AUDIT.value());
        }
        shopDetailMapper.insert(shopDetail);
    }

    @Override
    public void updateStatus(Long shopId, Integer status) {
        shopDetailMapper.updateStatus(shopId, status);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void changeShopStatusByContractTime(Date now) {
        // 获取状态需要改变为停业状态的店铺id列表
        List<Long> shopIdsToStop = shopDetailMapper.listShopIdsOfStatusChangeToStopByContractTime(now);
        // 获取状态需要改变为营业状态的店铺id列表
        List<Long> shopIdsToOpen = shopDetailMapper.listShopIdsOfStatusChangeToOpenByContractTime(now);
        if (CollUtil.isEmpty(shopIdsToOpen) && CollUtil.isEmpty(shopIdsToStop)) {
            // 没有店铺状态需要改变
            return;
        }
        // 改变店铺状态
        if (CollUtil.isNotEmpty(shopIdsToOpen)) {
            shopDetailMapper.batchUpdateShopStatusByShopIds(shopIdsToOpen, ShopStatus.STOP.value(), ShopStatus.OPEN.value());
        }
        if (CollUtil.isNotEmpty(shopIdsToStop)) {
            shopDetailMapper.batchUpdateShopStatusByShopIds(shopIdsToStop, ShopStatus.OPEN.value(), ShopStatus.STOP.value());
        }
        // 状态发生变化的店铺id列表
        List<Long> changeShopIds = CollUtil.unionAll(shopIdsToStop, shopIdsToOpen);
        if (CollUtil.isEmpty(changeShopIds)) {
            return;
        }
        // 清除状态发生变化的店铺缓存信息
        List<String> keyList = new ArrayList<>();
        changeShopIds.forEach(shopId -> {
            keyList.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);
        });
        // 下架店铺的商品
        RedisUtil.deleteBatch(keyList);
        productMapper.offlineProdByShopIds(changeShopIds);
        if (CollUtil.isNotEmpty(shopIdsToStop)) {
            applicationContext.publishEvent(new PopupOfflineShopLinkEvent(shopIdsToStop));
        }
        // 在es更新店铺下的商品（用于刷新商品在es的appDisplay）
        this.updateProdByShopIds(changeShopIds);
    }

    /**
     * 根据店铺id列表删除缓存
     *
     * @param shopIds
     */
    private void removeCacheByShopIds(List<Long> shopIds) {
        List<String> keyList = new ArrayList<>();
        shopIds.forEach(shopId -> {
            keyList.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);
        });
        RedisUtil.deleteBatch(keyList);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopSigningInfoDTO.shopId")
    public void updateSigningInfo(ShopSigningInfoDTO shopSigningInfoDTO) {
        ShopDetail oldShopDetail = shopDetailMapper.selectOne(Wrappers.lambdaQuery(ShopDetail.class).eq(ShopDetail::getShopId, shopSigningInfoDTO.getShopId()));
        ShopDetail newShopDetail = BeanUtil.map(oldShopDetail, ShopDetail.class);
        newShopDetail.setIsSupplier(shopSigningInfoDTO.getIsSupplier());
        newShopDetail.setType(shopSigningInfoDTO.getType());
        newShopDetail.setContractStartTime(DateUtil.beginOfDay(shopSigningInfoDTO.getContractStartTime()));
        newShopDetail.setContractEndTime(Objects.isNull(shopSigningInfoDTO.getContractEndTime()) ? null : getSaveEndOfDay(shopSigningInfoDTO.getContractEndTime()));
        // 当店铺状态处于营业中或者停业中时，店铺状态会受签约时间改变
        if (Objects.equals(newShopDetail.getShopStatus(), ShopStatus.OPEN.value()) || Objects.equals(newShopDetail.getShopStatus(), ShopStatus.STOP.value())) {
            Date now = new Date();
            // 记录店铺状态是否发生改变
            boolean isChangeStatus = false;
            if (now.compareTo(newShopDetail.getContractStartTime()) >= 0 &&(Objects.isNull(newShopDetail.getContractEndTime()) || now.compareTo(newShopDetail.getContractEndTime()) < 0)) {
                // 如果店铺的签约时间包含当前时间，则把店铺状态置为营业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.STOP.value());
                newShopDetail.setShopStatus(ShopStatus.OPEN.value());
                shopDetailMapper.updateById(newShopDetail);
            } else if (now.compareTo(newShopDetail.getContractStartTime()) < 0 || now.compareTo(newShopDetail.getContractEndTime()) >= 0) {
                // 如果店铺的签约时间不包含当前时间，则把店铺状态置为停业中
                isChangeStatus = Objects.equals(oldShopDetail.getShopStatus(), ShopStatus.OPEN.value());
                newShopDetail.setShopStatus(ShopStatus.STOP.value());
                shopDetailMapper.updateById(newShopDetail);
                // 修改商品状态为下架
                productMapper.offlineProdByShopIds(Collections.singletonList(shopSigningInfoDTO.getShopId()));
                // 删除弹窗关联
                applicationContext.publishEvent(new PopupDeleteLinkEvent(shopSigningInfoDTO.getShopId(), shopSigningInfoDTO.getShopId(), JumpType.SHOP.value(), null));
            }
            // 如果店铺状态发生变化
            if (isChangeStatus) {
                this.updateProdByShopIds(Collections.singletonList(newShopDetail.getShopId()));
            }
        }
        // 店铺违规下线、违规提交审核时，修改签约时间和店铺类型，不修改状态
        else {
            shopDetailMapper.updateById(newShopDetail);
        }
        // 单独更新签约结束时间
        update(new LambdaUpdateWrapper<>(ShopDetail.class)
                .set(ShopDetail::getContractEndTime, newShopDetail.getContractEndTime())
                .eq(ShopDetail::getShopId, newShopDetail.getShopId()));
    }

    @Override
    public void exportShop(AuditingInfoParam auditingInfoParam, HttpServletResponse response) {
        Integer paySysType = allinpayCompanyService.getIsAllinpay() ? PaySysType.ALLINPAY.value() : PaySysType.DEFAULT.value();
        auditingInfoParam.setPaySysType(paySysType);
        if (CollUtil.isNotEmpty(auditingInfoParam.getShopStatusList())) {
            auditingInfoParam.setShopStatus(auditingInfoParam.getShopStatusList().get(0));
        }
        List<ShopExportParam> shopExportList = shopDetailMapper.listExportByShopParam(auditingInfoParam);
        if (CollUtil.isEmpty(shopExportList)) {
            return;
        }
        ExcelWriter writer = ExcelUtil.getBigWriter();
        final List<String> exportCol = Arrays.asList(EXPORT_COL);

        Sheet sheet = writer.getSheet();
        // 设置列宽
        this.setColumnWidth(sheet);
        // 标题
        writer.merge(exportCol.size() - 1, I18nMessage.getMessage("yami.shop.detail.excel.title"));
        // 列名
        writer.writeRow(exportCol);
        int rowIndex = 2;
        for (ShopExportParam shopExportParam : shopExportList) {
            int col = -1;
            // 店铺名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getShopName());
            // 商家名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getMerchantName());
            // 店铺状态
            ShopStatus shopStatus = ShopStatus.instance(shopExportParam.getShopStatus());
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.isNull(shopStatus) ? "" : shopStatus.text());
            // 联系电话
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getTel());
//            // 邮箱
//            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getEmail());
//            // 所在省份
//            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getProvince());
//            // 所在城市
//            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCity());
//            // 所在区域
//            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getArea());
//            // 详细地址
//            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getShopAddress());
            // 简介
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getIntro());
            // 创建时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCreateTime());
            // 店铺类型
            ShopType shopType = ShopType.instance(shopExportParam.getType());
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.isNull(shopType) ? "" : shopType.text());
            // 签约起始时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getContractStartTime());
            // 签约终止时间
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getContractEndTime());
            // 经营范围
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getBusinessScope());
            // 统一社会信息代码
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCreditCode());
            // 企业名称
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getFirmName());
            // 住所
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getResidence());
            // 法定代表人
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getRepresentative());
            // 注册资本（万元）
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getCapital());
            // 成立日期
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, shopExportParam.getFoundTime());
            // 营业起始日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.nonNull(shopExportParam.getStartTime()) ? sdf.format(shopExportParam.getStartTime()) : "");
            // 营业终止日期
            PoiExcelUtil.mergeIfNeed(writer, rowIndex, rowIndex, ++col, col, Objects.nonNull(shopExportParam.getEndTime()) ? sdf.format(shopExportParam.getEndTime()) : "");
            ++rowIndex;
        }
        PoiExcelUtil.writeExcel(response, writer);
    }

    @Override
    public IPage<ShopHeadInfoDto> renovationShopPage(PageParam<ShopDetail> page, ShopSearchParam shopSearchParam) {
        return shopDetailMapper.renovationShopPage(page, shopSearchParam);
    }

    @Override
    public List<ShopHeadInfoDto> listRenovationShop(ShopSearchParam shopSearchParam) {
        if (CollUtil.isEmpty(shopSearchParam.getShopIds())) {
            return new ArrayList<>();
        }
        return shopDetailMapper.listRenovationShop(shopSearchParam);
    }

    @Override
    public List<ShopDetail> getShopDetailByShopIds(List<Long> shopIds) {
        return shopDetailMapper.getShopDetailByShopIds(shopIds);
    }


    private void setColumnWidth(Sheet sheet) {
        // 店铺名称
        sheet.setColumnWidth(0, 20 * 256);
        // 商家名称
        sheet.setColumnWidth(1, 20 * 256);
        // 店铺状态
        sheet.setColumnWidth(2, 20 * 256);
        // 联系电话
        sheet.setColumnWidth(3, 20 * 256);
//        // 邮箱
//        sheet.setColumnWidth(4, 20 * 256);
//        // 所在省份
//        sheet.setColumnWidth(5, 20 * 256);
//        // 所在城市
//        sheet.setColumnWidth(6, 20 * 256);
//        // 所在区域
//        sheet.setColumnWidth(7, 20 * 256);
//        // 详细地址
//        sheet.setColumnWidth(8, 60 * 256);
        // 简介
        sheet.setColumnWidth(4, 60 * 256);
        // 创建时间
        sheet.setColumnWidth(5, 20 * 256);
        // 店铺类型
        sheet.setColumnWidth(6, 20 * 256);
        // 签约起始时间
        sheet.setColumnWidth(7, 20 * 256);
        // 签约终止时间
        sheet.setColumnWidth(8, 20 * 256);
        // 经营范围
        sheet.setColumnWidth(9, 60 * 256);
        // 统一社会信息代码
        sheet.setColumnWidth(10, 20 * 256);
        // 企业名称
        sheet.setColumnWidth(11, 20 * 256);
        // 住所
        sheet.setColumnWidth(12, 30 * 256);
        // 法定代表人
        sheet.setColumnWidth(13, 20 * 256);
        // 注册资本（万元）
        sheet.setColumnWidth(14, 20 * 256);
        // 成立日期
        sheet.setColumnWidth(15, 20 * 256);
        // 营业起始日期
        sheet.setColumnWidth(16, 20 * 256);
        // 营业终止日期
        sheet.setColumnWidth(17, 20 * 256);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheNames = CacheNames.SHOP_DETAIL_ID_KEY, key = "#shopId")
    public void auditApply(Long eventId, Long shopId, String reapplyReason) {
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.isNull(shopDetail)) {
            // 未找到该店铺信息
            throw new YamiShopBindException("yami.store.not.exist");
        }
        if (!Objects.equals(shopDetail.getShopStatus(), ShopStatus.OFFLINE.value())) {
            throw new YamiShopBindException("店铺状态已发生变化，请刷新后重试");
        }
        // 更新店铺状态为待审核状态
        shopDetailMapper.updateStatus(shopId, ShopStatus.OFFLINE_AUDIT.value());

        // 更新事件状态
        offlineHandleEventService.updateToApply(eventId, reapplyReason);
    }

    @Override
    public void computeShopScore(Long shopId) {
        if (Objects.isNull(shopId)) {
            return;
        }
        Date endTime = new Date();
        Date startTime = DateUtils.getBeforeDay(endTime, -180);
        List<ShopDetailVO> shopScoreList = prodCommService.computeShopScore(startTime, shopId);
        // 修改店铺评分
        // 没有一条评论,店铺评分为0
        if (shopScoreList.isEmpty()) {
            ShopDetailVO shopDetailVO = new ShopDetailVO();
            shopDetailVO.setShopId(shopId);
            shopDetailVO.setShopScore(0.00);
            shopScoreList.add(shopDetailVO);
        }
        shopDetailMapper.batchUpdateShopScore(shopScoreList);
        // 清理一下店铺评分缓存
        RedisUtil.del(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAllinpayMember() {
        // 获取还没创建通联会员的商家id列表
        List<Long> shopIds = shopDetailMapper.listUnCreateMemberShopIds();
        if (CollUtil.isEmpty(shopIds)) {
            return;
        }

        shopDetailMapper.updateShopIsCreate(shopIds);
        // 已经开店的
        // 更新商家信息并且将对应商家的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
        shopDetailMapper.updateShopToStop(shopIds);

        // 提交开店申请的
        // 找出已经提交申请的商家的审核信息给予驳回，然后更改状态为申请中
        shopDetailMapper.updateShopToApplying(shopIds);
        shopAuditingService.updateToFail(shopIds);

        // 修改工商信息的
        // 给予驳回，更改最后成功的工商信息为待审核
        List<CompanyAuditing> needAuditList = companyAuditingService.getNeedAuditList();
        if (CollUtil.isNotEmpty(needAuditList)) {
            for (CompanyAuditing companyAuditing : needAuditList) {
                companyAuditing.setUpdateTime(new Date());
                companyAuditing.setStatus(AuditStatus.FAILAUDIT.value());
                companyAuditing.setRemarks("通联信息待完善");
                companyAuditingService.updateById(companyAuditing);
                // 把对应的工商信息设置为审核未通过状态
                ShopCompany shopCompany = new ShopCompany();
                shopCompany.setShopCompanyId(companyAuditing.getShopCompanyId());
                shopCompany.setStatus(AuditStatus.FAILAUDIT.value());
                shopCompanyService.update(new LambdaUpdateWrapper<ShopCompany>()
                        .set(ShopCompany::getStatus, AuditStatus.FAILAUDIT.value())
                        .eq(ShopCompany::getShopCompanyId, companyAuditing.getShopCompanyId()));
            }
        }
        shopCompanyService.update(new LambdaUpdateWrapper<ShopCompany>()
                .set(ShopCompany::getStatus, AuditStatus.WAITAUDIT.value())
                .eq(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value()));

        // 给所有商家都新增一个通联的钱包
        List<String> keys = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long shopId : shopIds) {
            saveShopWallet(shopId, true);
            // 删除商家的银行卡，需要重新绑定
            shopBankCardService.remove(new LambdaQueryWrapper<ShopBankCard>().in(ShopBankCard::getShopId, shopId));
            keys.add(CacheNames.SHOP_DETAIL_ID_KEY + CacheNames.UNION + shopId);

            // 将该店铺所有的商品下线状态
            productMapper.offlineProdByShopIds(Collections.singletonList(shopId));

            // 发送店铺违规下线事件
            applicationContext.publishEvent(new ShopChangeStatusEvent(shopId, ShopStatus.OFFLINE));
        }
        boolean notExist = shopWalletMapper.selectCount(new LambdaQueryWrapper<ShopWallet>()
                .eq(ShopWallet::getShopId, Constant.PLATFORM_SHOP_ID).eq(ShopWallet::getPaySysType, 1)) < 1;
        if (notExist) {
            // 给平台添加一个钱包
            saveShopWallet(Constant.PLATFORM_SHOP_ID, true);
        }
        // 在es更新店铺下的商品（用于刷新商品在es的appDisplay）
        this.updateProdByShopIds(shopIds);
        RedisUtil.del(keys);

        List<String> bizUserIds = new ArrayList<>(Constant.INITIAL_CAPACITY);
        for (Long shopId : shopIds) {
            bizUserIds.add(AllinpayConstant.SHOP + shopId);
        }
        // 批量创建会员
        for (String bizUserId : bizUserIds) {
            allinpayCompanyService.createCompanyMember(bizUserId);
        }
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void createAllinpayMemberByShopId(Long shopId) {
        // 该方法通联独有,可能平台开启通联支付的时候参数没配好，所以导致商家没能创建成功会员，那么在商家端登录的时候就要给商家无感创建一个
        if (!allinpayCompanyService.getIsAllinpay()) {
            return;
        }
        ShopDetail shopDetail = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.equals(shopDetail.getIsCreateMember(), 1)) {
            return;
        }
        shopDetailMapper.updateShopIsCreate(Collections.singletonList(shopId));
        Integer shopStatus = shopDetail.getShopStatus();
        if (Objects.equals(shopStatus, ShopStatus.OPEN.value())
                || Objects.equals(shopStatus, ShopStatus.STOP.value())
                || Objects.equals(shopStatus, ShopStatus.OFFLINE.value())
                || Objects.equals(shopStatus, ShopStatus.OFFLINE_AUDIT.value())) {
            // 已经开店的
            // 更新商家信息并且将对应商家的通联商家改完平台下线，等绑定了手机，设置了企业信息，影印件审核通过后，通联审核通过即可恢复原状态
            shopDetailMapper.updateShopToStop(Collections.singletonList(shopId));
        } else if (Objects.equals(shopStatus, ShopStatus.OPEN_AWAIT_AUDIT.value())) {
            // 提交开店申请的
            // 找出已经提交申请的商家的审核信息给予驳回，然后更改状态为申请中
            shopDetailMapper.updateShopToApplying(Collections.singletonList(shopId));
            shopAuditingService.updateToFail(Collections.singletonList(shopId));
        }
        CompanyAuditing companyAuditing = companyAuditingService.getLatestAuditingByShopId(shopId);
        if (Objects.nonNull(companyAuditing)) {
            if (Objects.equals(companyAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
                // 修改工商信息的
                // 给予驳回，更改最后成功的工商信息为待审核
                companyAuditing.setRemarks("通联信息待完善");
                companyAuditing.setStatus(AuditStatus.FAILAUDIT.value());
                companyAuditingService.updateById(companyAuditing);
                // 把对应的工商信息设置为审核未通过状态
                ShopCompany shopCompany = new ShopCompany();
                shopCompany.setStatus(AuditStatus.FAILAUDIT.value());
                shopCompany.setShopCompanyId(companyAuditing.getShopCompanyId());
                shopCompanyService.updateById(shopCompany);
            }
        }
        // 修改商家成功的工商信息为待审核
        shopCompanyService.update(new LambdaUpdateWrapper<ShopCompany>()
                .set(ShopCompany::getStatus, AuditStatus.WAITAUDIT.value())
                .eq(ShopCompany::getShopId, shopId)
                .eq(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value()));

        // 给商家新增一个通联的钱包
        saveShopWallet(shopId, true);
        // 删除商家的银行卡，需要重新绑定
        shopBankCardService.remove(new LambdaQueryWrapper<ShopBankCard>().in(ShopBankCard::getShopId, shopId));
        // 将该店铺所有的商品下线状态
        productMapper.offlineProdByShopIds(Collections.singletonList(shopId));
        // 在es更新店铺下的商品（用于刷新商品在es的appDisplay）
        this.updateProdByShopIds(Collections.singletonList(shopId));
        // 发送店铺违规下线事件
        applicationContext.publishEvent(new ShopChangeStatusEvent(shopId, ShopStatus.OFFLINE));
        // 创建会员
        allinpayCompanyService.createCompanyMember(AllinpayConstant.SHOP + shopId);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateAllinpayIdCardStatus(String bizUserId, Integer status) {
        Long shopId = Long.valueOf(bizUserId.substring(AllinpayConstant.SHOP_LENGTH));
        log.info("店铺{}影印件更新，影印件状态为{}", shopId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
        // 影印件回调只会在企业审核通过后，所以这里再次更新一下，可能之前设置企业信息回调失败了
        updateShopAllinpayStatusToSuccess(shopId);
        shopDetailMapper.updateAllinpayIdCardStatus(shopId, status);
        if (!Objects.equals(status, IdCardCollectProcessStatus.ALL.value())) {
            log.info("店铺{}影印件更新，影印件状态为{}，未全部通过审核", shopId, Objects.requireNonNull(IdCardCollectProcessStatus.instance(status)).str());
            return;
        }
        // 如果审核都通过，将对应店铺上线
        shopDetailMapper.updateShopToOpen(shopId);
        ShopAuditing shopAuditing = shopAuditingService.getOne(new LambdaQueryWrapper<ShopAuditing>().eq(ShopAuditing::getShopId, shopId));
        if (!Objects.equals(shopAuditing.getStatus(), AuditStatus.SUCCESSAUDIT.value())) {
            log.info("店铺{}影印件更新,全部通过审核,进行开店回调，自动审核店铺", shopId);
            // 审核还没成功代表这是开店的回调
            ShopAuditingParam shopAuditingDTO = BeanUtil.map(shopAuditing, ShopAuditingParam.class);
            shopAuditingDTO.setStatus(AuditStatus.SUCCESSAUDIT.value());
            shopAuditingDTO.setAuditorId(null);
            // 自动审核店铺
            audit(shopAuditingDTO);
        } else {
            log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，自动审核工商信息", shopId);
            // 修改工商信息回调
            CompanyAuditing companyAuditing = companyAuditingService.getLatestAuditingByShopId(shopId);
            if (Objects.isNull(companyAuditing)) {
                log.error("影印件回调，工商审核信息不存在{}", bizUserId);
                return;
            }
            if (Objects.equals(companyAuditing.getStatus(), AuditStatus.WAITAUDIT.value())) {
                log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为待审核状态", shopId);
                companyAuditing.setStatus(AuditStatus.SUCCESSAUDIT.value());
                companyAuditingService.updateById(companyAuditing);

                shopCompanyService.update(new LambdaUpdateWrapper<ShopCompany>()
                        .set(ShopCompany::getStatus, AuditStatus.FAILAUDIT.value())
                        .eq(ShopCompany::getShopId, shopId));
                // 把对应的工商信息设置为启用状态
                shopCompanyService.update(new LambdaUpdateWrapper<ShopCompany>()
                        .set(ShopCompany::getStatus, AuditStatus.SUCCESSAUDIT.value())
                        .eq(ShopCompany::getShopCompanyId, companyAuditing.getShopCompanyId()));
            } else if (Objects.equals(companyAuditing.getStatus(), AuditStatus.FAILAUDIT.value())) {
                log.info("店铺{}影印件更新,全部通过审核,进行修改工商信息回调，工商信息为失败状态", shopId);
                // 审核不通过的工商信息删了
                shopCompanyService.remove(new LambdaQueryWrapper<ShopCompany>().eq(ShopCompany::getShopId, shopId)
                        .eq(ShopCompany::getStatus, AuditStatus.FAILAUDIT.value()));
            }
        }
    }

    @Override
    public void updateShopAllinpayStatusToSuccess(Long shopId) {
        ShopDetail shopDetailVO = shopDetailMapper.selectShopDetailById(shopId);
        if (Objects.isNull(shopDetailVO)) {
            return;
        }
        if (Objects.equals(shopDetailVO.getCompanyInfoProcessStatus(), CompanyInfoProcessStatus.SUCCESS.value())) {
            return;
        }
        shopDetailMapper.updateShopAuditSuccess(shopId);
    }

    private void saveShopWallet(Long shopId, boolean isAllinpay) {
        ShopWallet shopWallet = new ShopWallet();
        shopWallet.setVersion(0L);
        shopWallet.setUnsettledAmount(0D);
        shopWallet.setSettledAmount(0D);
        shopWallet.setFreezeAmount(0D);
        shopWallet.setTotalSettledAmount(0D);
        shopWallet.setShopId(shopId);
        shopWallet.setPaySysType(isAllinpay ? 1 : 0);
        shopWalletMapper.insert(shopWallet);
    }

    private Date getSaveEndOfDay(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(DateUtil.endOfDay(date));
        // 防止时间进位
        calendar.set(Calendar.MILLISECOND, 0);
        return calendar.getTime();
    }

    /**
     * 检验店铺信息是否正确
     *
     * @param shopDetail 店铺基本信息
     * @param isCreate   true: 创建时校验， false: 更新时校验
     */
    private void checkShopInfo(ShopDetail shopDetail, Boolean isCreate) {
        String shopName = shopDetail.getShopName().trim();
        // 店铺名称
        if (StrUtil.isNotBlank(shopName)) {
            shopDetail.setShopName(shopDetail.getShopName().trim());
        } else {
            throw new YamiShopBindException("yami.shop.name.not.blank");
        }
        if (shopDetailMapper.selectCount(Wrappers.lambdaQuery(ShopDetail.class)
                .eq(ShopDetail::getShopName, shopDetail.getShopName())
                .ne(ShopDetail::getShopId, shopDetail.getShopId())
                .ne(ShopDetail::getShopStatus, ShopStatus.NOTOPEN.value())) > 0) {
            // 已有相同名称
            throw new YamiShopBindException("yami.shop.name.have.already");
        }
    }

    /**
     * 发送事件提醒es更新商品信息
     *
     * @param shopIds
     */
    private void updateProdByShopIds(List<Long> shopIds) {
        List<Long> prodIds = productMapper.listIdByShopIds(shopIds);
        if (CollUtil.isEmpty(prodIds)) {
            return;
        }
        eventPublisher.publishEvent(new EsProductUpdateEvent(null, prodIds, EsOperationType.UPDATE_BATCH));
    }
}
